<template>
  <div class="canvas-item">
    <canvas type="2d" class="canvas-result" :id="mac" :width="280" :height="280"></canvas>
  </div>
</template>

<script lang="ts" setup>
  import { ref, reactive, computed, onMounted, onUnmounted } from 'vue';
  import * as constants from '@/config/constants';
  import PenWorker from '@/components/Pen/pen.worker?worker';
  import { websiteConfig } from '@/config/website.config';
  import { useCourse } from '@/store/modules/course';
  import { useIndexedDB } from '@/store/modules/indexedDB';
  import {
    beforePreCompute,
    getPageRegionByKey,
    getRealPreCompute,
    getRealWordData,
    preCompute
  } from '@/api/course';
  import { saveImageToLocal, saveSqliteData } from '@/utils/ipcRenderer';
  import {ocrImage, uploadFile} from "@/api/base";
  import crypto from "@/utils/crypto";
  import {format} from "date-fns";
  import { ossUpload } from "@/utils/ossUtil";

  const props = defineProps({
    mac: {
      type: String,
      default: '',
    },
    studentInfo: {
      type: Object,
      default: null,
    },
  });
  const readyState = ref(0);
  const battery = reactive({
    loading: true,
    percentage: 0,
    charge: true,
  });
  const logIngoData = ref<any[]>([]);
  const connectionStatusText = computed(() => {
    return ['连接中...', '已连接', '断开中...', '已断开'][readyState.value];
  });
  const connectionStatusClass = computed(() => {
    return ['animate-pulse', 'text-green-400', 'text-red-600', 'text-red-600'][readyState.value];
  });
  const canvas: any = document.getElementById(props.mac);
  const worker: any = new PenWorker();
  const loadBookData = ref(false)
  const requestBookDataTime = ref(0);
  async function drawImage(data) {
    try {
      let c1: any = document.createElement('canvas');
      c1.width = data.image.width;
      c1.height = data.image.height;
      let c1Ctx: any = c1.getContext('2d');
      c1Ctx.putImageData(data.image, 0, 0);
      if (data.regionType === 1) {
        const r1 = await uploadFile(`${props.mac}-handWrite-${Date.now()}.png`, 'COMMON', c1.toDataURL());
        const r2 = await ocrImage({ url: r1 });
        const penData = useCourse().getCoursePenData;
        const findIndex = penData.findIndex((i) => i.mac === props.mac);
        if (findIndex > -1) {
          penData[findIndex].studentInfo = r2;
        }
        useCourse().setCoursePenData(penData);
      } else {
        const fileName = `${props.mac}-handWrite-${Date.now()}.json`;
        const blobData = new Blob([JSON.stringify(data.tempPenData)], { type: 'text/plain' })
        const file = new File([blobData], fileName, { type: 'text/plain' })
        ossUpload(`upload/HANDWRITING/${format(Date.now(), 'yyyyMMdd')}/`, file).then((res) => {
          const temp = {
            "index": data.index,
            "regionId": data.regionId,
            "type": 1,
            "url": 'http://tr-pen.oss-cn-hangzhou.aliyuncs.com/' + res.url
          }
          beforePreCompute(crypto.encrypt(
            JSON.stringify(temp)
          )).then(async r2 => {
            let preComputeTimer: any = null
            let identificationCode = r2
            async function getRealPreCompute () {
              try {
                const r3 = await getRealWordData({identification: identificationCode})
                if (r3.code === 200) {
                  await saveWordData(temp, data, r3.data, c1)
                  clearTimeout(preComputeTimer)
                } else if (r3.code === 60004) {
                  preComputeTimer = setTimeout(async() => {
                    await getRealPreCompute()
                  }, 1500)
                } else if (r3.code === 60002) {
                  clearTimeout(preComputeTimer)
                } else if (r3.code === 60003) {
                  clearTimeout(preComputeTimer)
                }
              } catch (e) {
                preComputeTimer = setTimeout(async() => {
                  await getRealPreCompute()
                }, 1500)
              }
            }
            await getRealPreCompute();

          })
        });
      }
    } catch (e) {
      console.log(e);
    }
  }
  // 保存笔迹数据
  async function saveWordData (temp, data, wordData, c1) {
    const pointKey = `${useCourse().getCurrentCourseData.courseId}-${props.mac}-${props.studentInfo.id}-${temp.regionId}-${temp.index}`
    // 保存笔迹数据 sqlite indexeddb各一份
    const oldData = await useIndexedDB().getPointDB(pointKey)
    if (!oldData) {
      const sqlData = {
        courseId: useCourse().getCurrentCourseData.courseId,
        isBad: 0,
        isGood: 0,
        mac: props.mac,
        studentId: props.studentInfo.id,
        studentName: props.studentInfo.name,
        studentPic: props.studentInfo.pic,
        regionId: data.regionId,
        regionIndex: data.index,
        practiceTime: format(new Date(), 'yyyy-MM-dd hh:mm:ss'),
        jsonData: JSON.stringify(wordData),
        bookData: JSON.stringify({
          textBookId: data.textBookId,
          textBookPageId: data.textBookPageId,
        })
      }
      // 六个维度评分
      const scoreData = [
        wordData.scope.orderCalculationScore,
        wordData.scope.structureCalculationScore,
        wordData.scope.speedCalculationScore,
        wordData.scope.strengthCalculationScore,
        wordData.scope.strokeCalculationScore,
        wordData.scope.countCalculationScore,
      ];
      // 平均分
      const averageScore = scoreData.reduce((prve, curr) => {
        return prve + curr;
      }, 0) / 6;
      const integralResult: any = useCourse().calcIntegralSettingData(averageScore)
      if (integralResult.scope === 1) {
        sqlData.isBad = 1
      }  else if (integralResult.scope === 3) {
        sqlData.isGood = 1
      }
      await saveSqliteData({
        action: 'add',
        info: sqlData
      })
      await useIndexedDB().setPointDB(pointKey,{
        jsonData: wordData,
        bookData: data
      });
      await saveImageToLocal(`${pointKey}.webp`, c1.toDataURL())

    }
  }
  function connectionWorker() {
    const canvas: any = document.getElementById(props.mac);
    const canvasWorker: any = canvas.transferControlToOffscreen();
    //控制权转让
    worker.postMessage(
      {
        command: constants.WORKER_INIT,
        data: {
          canvas: canvasWorker,
          mac: props.mac,
          ws: `ws://${websiteConfig.apServerUrl}/ws/newap/${props.mac}`,
          bookMapData: JSON.stringify(useCourse().getBookMapData),
        },
      },
      [canvasWorker]
    );
    worker.onmessage = async (e) => {
      const {
        data: { command, data },
      } = e;
      // console.log("main", command, data);
      switch (command) {
        case constants.WORKER_WEBSOCKET_READY_STATE:
          readyState.value = data.readyState;
          break;
        case constants.WORKER_PEN_BATTERY:
          if (battery.loading) battery.loading = false;
          battery.percentage = data.power;
          battery.charge = !Boolean(data.charge);
          break;
        case constants.WORKER_GET_OFFLINE_SIZE_NUMBER:
          logIngoData.value.push(`离线数据量：${data.data} bytes`);
          break;
        case constants.GET_PEN_AUTO_OFF:
          logIngoData.value.push(`自动关机：${data.data}min`);
          break;
        case constants.SET_PEN_AUTO_OFF:
          logIngoData.value.push(`设置自动关机：${['成功', '失败'][data.data]}`);
          break;
        case constants.GET_CODE_POINT_VALUE:
          logIngoData.value.push(`码点类型：${data.data}`);
          break;
        case constants.AP_TEST:
          logIngoData.value.push(`测试命令：${data.data}`);
          break;
        case constants.RETURN_PEN_IMAGE:
          if (data.regionType === 1) {
            await drawImage(data);
          } else {
            if (!props.studentInfo) {
              console.log('未匹配学生，不写入数据')
              return false
            } else {
              await drawImage(data);
            }
          }
          break;
        case constants.PEN_DATA:

          const bookMapData = useCourse().getBookMapData;
          const textBookPageId = `${data.data.BookID}-${data.data.OwnerID}-${data.data.PageID}-${data.data.SectionID}`;
          const bIndex = bookMapData.findIndex((i) => {
            return (
              i.textBookPageId === textBookPageId
            );
          });
          if (bIndex === -1) {
            if (Date.now() - requestBookDataTime.value > 1000) {
              if(loadBookData.value) return
              loadBookData.value = true
              try {
                const r1 = await getPageRegionByKey({
                  book: data.data.BookID,
                  owner: data.data.OwnerID,
                  page: data.data.PageID,
                  section: data.data.SectionID,
                });
                const allRegion: any[] = [];
                const regionMap = {};
                r1.regionList.forEach((item) => {
                  const regions = JSON.parse(item.regionInfo);
                  regionMap[item.id] = {
                    tempPic: item.regionPic,
                    num: regions.length,
                  };
                  regions.forEach((val) => {
                    allRegion.push({
                      ...val,
                      regionId: item.id,
                      regionType: item.regionType,
                      regionPic: item.regionPic,
                      bookWidth: r1.width,
                      bookHeight: r1.height,
                      textBookId: item.textBookId,
                      textBookPageId: r1.id,
                    });
                  });
                });
                r1.regionList = allRegion;
                r1.regionMap = regionMap;
                r1.textBookPageId = textBookPageId;
                bookMapData.push(r1);
                useCourse().setBookData(bookMapData);
                worker.postMessage(
                  {
                    command: constants.UPDATE_BOOK_DATA,
                    data: {
                      bookMapData: JSON.stringify(bookMapData),
                    },
                  },
                  []
                );

                loadBookData.value = false
              } catch (e) {
                loadBookData.value = false
              }
            }
          }
          break;
        default:
          break;
      }
    };
    worker.onerror = (e) => {
      console.error(props.mac, 'worker', e);
    };
  }
  onMounted(() => {
    if (props.mac?.length > 8) {
      connectionWorker();
    }
  });
  onUnmounted(() => {
    worker.terminate();
  });
</script>
